/*
 * =====================================================================================
 *
 *       Filename:  unit/src/unit_test_buffer.c
 *
 *    Description:  lich unit test 
 *
 *        Version:  1.0
 *        Created:  10/08/2017 16:18:25 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Gabe
 *        Company:  
 *
 * =====================================================================================
 */
#include "config.h"

#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <dirent.h>
#include <ctype.h>
#include <libgen.h>

#define DBG_SUBSYS S_LIBINTERFACE

#include "configure.h"
#include "env.h"
#include "adt.h"
#include "net_table.h"
#include "lichstor.h"
#include "cluster.h"
#include "metadata.h"
#include "lich_md.h"
#include "storage.h"
#include "volume.h"
#include "lichbd.h"
#include "license.h"
#include "md_map.h"
#include "net_global.h"
#include "dbg.h"

static void __test_buffer_write(int get_off, int get_size)
{
        int i;
        char tmp[49], out[49];
        buffer_t buf;

        mbuffer_init(&buf, 0);

        memset(tmp, 0x0, 49);
        memset(out, 0x0, 49);

        for (i = 0; i < 48; i++) {
                memset(tmp + i, '0' + (i % 8), 1);
        }
        printf("tmp1:");
        for (i = 0; i < 48; i++) {
                if (i % 16 == 0) {
                        printf(" ");
                }
                printf("%c", tmp[i]);
        }
        printf("\n");

        mbuffer_copy(&buf, tmp, 48);
        mbuffer_read(&buf, out + get_off, get_off, get_size);

        printf("out1:");
        for (i = 0; i < 48; i++) {
                if (i % 16 == 0) {
                        printf(" ");
                }
                if (out[i] == 0)
                        printf(" ");
                else
                        printf("%c", out[i]);
        }
        printf("\n");

        for (i = get_off; i < get_off + get_size; i++) {
                out[i] = '9';
        }

        printf("out2:");
        for (i = 0; i < 48; i++) {
                if (i % 16 == 0) {
                        printf(" ");
                }
                if (out[i] == 0)
                        printf(" ");
                else
                        printf("%c", out[i]);
        }
        printf("\n");

        mbuffer_write(&buf, out + get_off, get_off, get_size);
        mbuffer_get(&buf, out, buf.len);

        printf("out3:");
        for (i = 0; i < 48; i++) {
                if (i % 16 == 0) {
                        printf(" ");
                }
                if (out[i] == 0)
                        printf(" ");
                else
                        printf("%c", out[i]);
        }
        printf("\n\n");

        mbuffer_free(&buf);
}

void test_buffer_write()
{
        __test_buffer_write(0, 8);
        __test_buffer_write(4, 8);
        __test_buffer_write(8, 8);
        __test_buffer_write(0, 16);

        __test_buffer_write(16, 8);
        __test_buffer_write(20, 8);
        __test_buffer_write(24, 8);
        __test_buffer_write(16, 16);

        __test_buffer_write(32, 8);
        __test_buffer_write(36, 8);
        __test_buffer_write(40, 8);
        __test_buffer_write(32, 16);

        __test_buffer_write(0, 24);
        __test_buffer_write(4, 24);
        __test_buffer_write(8, 24);

        __test_buffer_write(12, 24);
        __test_buffer_write(16, 24);
        __test_buffer_write(20, 24);
        __test_buffer_write(24, 24);

        __test_buffer_write(0, 48);
}

static void __test_buffer_compare(char *data1, int size1, char *data2, int size2)
{
        int ret;
        buffer_t buf1;
        buffer_t buf2;

        mbuffer_init(&buf1, 0);
        mbuffer_init(&buf2, 0);

        mbuffer_copy(&buf1, data1, size1);
        mbuffer_copy(&buf2, data2, size2);

        ret = mbuffer_compare(&buf1, &buf2);
        if (ret) {
                printf("compare size %2d %2d not match!\n", size1, size2);
        } else {
                printf("compare size %2d %2d is same.\n", size1, size2);
        }

        mbuffer_free(&buf1);
        mbuffer_free(&buf2);
}

void test_buffer_compare()
{
        int i;
        char data[64];

        for (i = 0; i < 32; i++) {
                sprintf(data + i * 2, "%02x", i);
        }

        __test_buffer_compare(data, 8, data, 8);
        __test_buffer_compare(data, 16, data, 16);
        __test_buffer_compare(data, 24, data, 24);
        __test_buffer_compare(data, 32, data, 32);

        __test_buffer_compare(data, 8, data, 16);
        __test_buffer_compare(data, 16, data, 24);
        __test_buffer_compare(data, 24, data, 32);

        __test_buffer_compare(data, 8, data + 1, 8);
        __test_buffer_compare(data, 16, data + 1, 16);
        __test_buffer_compare(data, 24, data + 1, 24);
        __test_buffer_compare(data, 32, data + 1, 32);
}

static void __test_buffer_find(char *data, int size1, char *find, int size2)
{
        int idx;
        buffer_t buf1;

        mbuffer_init(&buf1, 0);
        mbuffer_copy(&buf1, data, size1);

        idx = mbuffer_find(&buf1, find, size2);
        if (idx < 0) {
                printf("from %s find %s len %d not found\n", data, find, size2);
        } else {
                printf("from %s find %s len %d  idx %d\n", data, find, size2, idx);
        }

        mbuffer_free(&buf1);
}

void test_buffer_find()
{
        char *data = "xyz0xyz1xyz2xyz3xyz4xyz5xyz6xyz7xyz8xyz9xyzaxyzbxyzcxyzdxyzexyzf";
        char find[64] = {0};

        strcpy(find, "xyz0");
        __test_buffer_find(data, 64, find, 4);

        strcpy(find, "xyz1xyz2");
        __test_buffer_find(data, 64, find, 8);

        strcpy(find, "xyz3");
        __test_buffer_find(data, 64, find, 4);

        strcpy(find, "z3xy");
        __test_buffer_find(data, 64, find, 4);

        strcpy(find, "xyz4");
        __test_buffer_find(data, 64, find, 4);

        strcpy(find, "xyzf");
        __test_buffer_find(data, 64, find, 4);

        strcpy(find, "xyz2xyz3xyz4xyz5");
        __test_buffer_find(data, 64, find, 16);

        strcpy(find, "xyz2xyz3xyz4xyz5xyz6xyz7xyz8xyz9xyzaxyzbxyzcxyzd");
        __test_buffer_find(data, 64, find, 48);

        strcpy(find, "xyzx");
        __test_buffer_find(data, 64, find, 4);
}

static void __buffer_format_output(buffer_t *buf)
{
        uint32_t i;
        seg_t *seg;

        struct list_head *pos, *n;
        list_for_each_safe(pos, n, &buf->list) {
                seg = (seg_t *)pos;

                for (i = 0; i < seg->len; i++) {
                        printf("%c", *((char *)seg->handler.ptr + i));
                }
                printf(" ");
        }

        printf("\n");
}

static void __test_buffer_compress(char *data, int size, int len)
{
        int left, offset, cp;
        buffer_t buf;

        mbuffer_init(&buf, 0);

        offset = 0;
        left = size;
        while (left) {
                cp = _min(left, len);

                mbuffer_appendmem(&buf, data + offset, cp);
                offset += cp;
                left -= cp;
        }

        printf("buf:");
        __buffer_format_output(&buf);

        mbuffer_compress(&buf);

        printf("compress:");
        __buffer_format_output(&buf);

        if (mbuffer_ncmp(&buf, 0, data, buf.len)) {
                printf("==============not compare===========\n");
        }
}

void test_buffer_compress()
{
        char *data = "xyz0xyz1xyz2xyz3xyz4xyz5xyz6xyz7xyz8xyz9xyzaxyzbxyzcxyzdxyzexyzf";

        __test_buffer_compress(data, 64, 2);
        __test_buffer_compress(data, 64, 4);
        __test_buffer_compress(data, 64, 8);
        __test_buffer_compress(data, 64, 12);
        __test_buffer_compress(data, 64, 16);
}

/*need change #define BUFFER_SEG_MAX (512 * 1024) to #define BUFFER_SEG_MAX (16) in ylib/lib/buffer.c*/
int unit_test_buffer(const char *func)
{
        if (!strcmp(func, "mbuffer_write")) {
                test_buffer_write();
        } else if (!strcmp(func, "mbuffer_compare")) {
                test_buffer_compare();
        } else if (!strcmp(func, "mbuffer_find")) {
                test_buffer_find();
        } else if (!strcmp(func, "mbuffer_compress")) {
                test_buffer_compress();
        } else {
                printf("func %s not found\n", func);
        }
        return 0;
}
